#pragma once
#include <stdarg.h>
#include <stdbool.h>
#include <time.h>
#include <mutex>
#include "../include/std.h"

#define CPP_LOG_VERSION "1.0.5"

#define LOG_INIT(...)  CLog::GetIns()->Init(__VA_ARGS__)
#define log_trace(...) CLog::GetIns()->Log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) CLog::GetIns()->Log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...)  CLog::GetIns()->Log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...)  CLog::GetIns()->Log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) CLog::GetIns()->Log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) CLog::GetIns()->Log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
#define log_imp(...)   CLog::GetIns()->Log(LOG_IMP, __FILE__, __LINE__, __VA_ARGS__)

#define log_hex(name, data, len)   CLog::GetIns()->HexLog(__FILE__, __LINE__, name, (const BYTE*)data, len)
#define log_hex_buf(name, std_buf) log_hex(name, std_buf.data(), std_buf.size())

enum
{
    LOG_TRACE,
    LOG_DEBUG,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR,
    LOG_FATAL,
    LOG_IMP, // 重要信息(IMPORTANT)
    LOG_MAX
};

class CLog
{
public:
    CLog() {};
    ~CLog();
    static CLog* GetIns();

    int Init(const char* pszFile, int iLogLevel = LOG_TRACE, int iPrintLevel = LOG_TRACE, int iSize = -1);
    /*初始化
     * pszFile   log文件名
     * iLogLevel 日志等级
     * iPrintLevel   在屏幕上打印的日志等级
     * iSize     单个日志文件长度最大值，单位MB。超过这个值会分成多个文件存储。-1表示无限制。
     * 说明：若要设置iSize，pszFile必须使用.log作为扩展名。如果pszFile是相对路径，会在初始化时转为绝对路径，不会随工作目录变化。
     */
    void Log(int level, const char* file, int line, const char* fmt, ...);
    void LogToFile(int level, const char* file, int line, const char* fmt, va_list va);
    void Print(int level, const char* fmt, va_list va);
    void HexLog(const char* file, int line, const char* pszName, const BYTE* data, int iLen);

protected:
    FILE* m_pstFile   = NULL;
    int m_iLogLevel   = LOG_MAX;
    int m_iPrintLevel = LOG_MAX;
    std::mutex m_objLock;

    string m_strFile;
    string m_strPrefix; // 创建新文件时使用的文件名前缀
    U64 m_u64Size = 0;

    inline static U32 ThrdID();
    int MoveLogFile();
};
